package com.yhw.srb.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yhw.common.exception.Assert;
import com.yhw.common.result.ResponseEnum;
import com.yhw.srb.core.enums.LendStatusEnum;
import com.yhw.srb.core.enums.TransTypeEnum;
import com.yhw.srb.core.hfb.FormHelper;
import com.yhw.srb.core.hfb.HfbConst;
import com.yhw.srb.core.hfb.RequestHelper;
import com.yhw.srb.core.mapper.*;
import com.yhw.srb.core.pojo.bo.TransFlowBO;
import com.yhw.srb.core.pojo.entity.Lend;
import com.yhw.srb.core.pojo.entity.LendItem;
import com.yhw.srb.core.pojo.entity.LendItemReturn;
import com.yhw.srb.core.pojo.entity.LendReturn;
import com.yhw.srb.core.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yhw.srb.core.util.LendNoUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author yhw
 * @since 2022-08-29
 */
@Service
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {

    @Resource
    private LendMapper lendMapper;

    @Resource
    private UserBindService userBindService;

    @Resource
    private UserAccountService userAccountService;

    @Resource
    private LendItemReturnService lendItemReturnService;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private LendReturnMapper lendReturnMapper;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private LendItemReturnMapper lendItemReturnMapper;

    @Resource
    private LendItemMapper lendItemMapper;

    @Override
    public List<LendReturn> selectByLendId(Long lendId) {
        LambdaQueryWrapper<LendReturn> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LendReturn::getLendId, lendId);
        List<LendReturn> lendReturnList = baseMapper.selectList(queryWrapper);
        return lendReturnList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String commitReturn(Long lendReturnId, Long userId) {

        //获取还款记录
        LendReturn lendReturn = baseMapper.selectById(lendReturnId);

        //判断账号余额是否充足
        BigDecimal amount = userAccountService.getAccount(userId);
        Assert.isTrue(amount.doubleValue() >= lendReturn.getTotal().doubleValue(),
                ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);  // NOT_SUFFICIENT_FUNDS_ERROR(307, "余额不足")

        Long lendId = lendReturn.getLendId();   // 标的id
        Lend lend = lendMapper.selectById(lendId);  // 标的

        String bindCode = userBindService.getBindCodeByUserId(userId);  //获取借款人code


        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        //商户商品名称
        paramMap.put("agentGoodsName", lend.getTitle());
        //批次号
        paramMap.put("agentBatchNo",lendReturn.getReturnNo());
        //还款人绑定协议号
        paramMap.put("fromBindCode", bindCode);
        //还款总额
        paramMap.put("totalAmt", lendReturn.getTotal());
        //备注
        paramMap.put("note", "");

        //还款明细
        List<Map<String, Object>> lendItemReturnDetailList = lendItemReturnService.addReturnDetail(lendReturnId);
        paramMap.put("data", JSONObject.toJSONString(lendItemReturnDetailList));

        paramMap.put("voteFeeAmt", new BigDecimal(0));  //手续费
        paramMap.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        paramMap.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign", sign);

        //构建 自动提交 字符串表单
        String formStr = FormHelper.buildForm(HfbConst.BORROW_RETURN_URL, paramMap);

        return formStr;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notify(Map<String, Object> paramMap) {

        /*
            1.接口的幂等性
            2.更新用户账户 借款人 投资人
            3.新增流水
            4.还款表 更新状态 更新实际发生的还款时间 是否最后一期还款 手续费
            5.回款表 更新状态 更新实际发生的还款时间
            6.标的投资表 更新 实际收益
            7.如果是最后一期 就要更新 标的 状态
         */

        // 接口的幂等性
        String agentBatchNo = (String)paramMap.get("agentBatchNo"); //还款编号

        boolean result = transFlowService.isSaveTransFlow(agentBatchNo);
        if(result){
            log.warn("幂等性返回");
            return;
        }

        // 更新 借款人 账户
        LambdaQueryWrapper<LendReturn> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LendReturn::getReturnNo,agentBatchNo);
        LendReturn lendReturn = baseMapper.selectOne(queryWrapper);   // 获取还款数据

        // 更新 还款表状态
        String voteFeeAmt = (String)paramMap.get("voteFeeAmt");
        lendReturn.setFee(new BigDecimal(voteFeeAmt));  //手续费

        lendReturn.setStatus(1); // 状态（0-未归还 1-已归还）
        lendReturn.setRealReturnTime(LocalDateTime.now());  // 更新实际发生的还款时间

        lendReturnMapper.updateById(lendReturn);

        // 如果是最后一期 就要更新 标的 状态
        Boolean last = lendReturn.getLast();  // 是否最后一期
        Long lendId = lendReturn.getLendId();  //标的id
        Lend lend = lendMapper.selectById(lendId); //标的
        if (last){
            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());  // PAY_OK(3, "已结清")
            lendMapper.updateById(lend);
        }

        BigDecimal totalAmt = new BigDecimal((String)paramMap.get("totalAmt")); //还款金额
        String bindCode = userBindService.getBindCodeByUserId(lendReturn.getUserId());
        userAccountMapper.updateAccount(bindCode, totalAmt.negate(), new BigDecimal(0));  // 更新 借款人 账户

        //借款人交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);

        // 更新 投资人 账户
        List<LendItemReturn> lendItemReturns = lendItemReturnService.selectLendItemReturnList(lendReturn.getId()); //根据还款id获取回款列表
        for (LendItemReturn lendItemReturn : lendItemReturns) {
            // 回款表 更新状态 更新实际发生的还款时间
            lendItemReturn.setStatus(1); //更新状态  状态（0-未归还 1-已归还）
            lendItemReturn.setRealReturnTime(LocalDateTime.now()); // 更新实际发生的还款时间
            lendItemReturnMapper.updateById(lendItemReturn);

            // 标的投资表 更新 实际收益
            Long lendItemId = lendItemReturn.getLendItemId(); // 投资表id
            LendItem lendItem = lendItemMapper.selectById(lendItemId); // 投资表
            lendItem.setRealAmount(lendItem.getRealAmount().add(lendItemReturn.getInterest())); // 更新 实际收益
            lendItemMapper.updateById(lendItem);

            //投资账号转入金额
            String investBindCode = userBindService.getBindCodeByUserId(lendItemReturn.getInvestUserId());
            userAccountMapper.updateAccount(investBindCode, lendItemReturn.getTotal(), new BigDecimal(0)); // 更新 投资人 账户

            //投资人交易流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    lendItemReturn.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle()); // INVEST_BACK(7,"出借回款"),
            transFlowService.saveTransFlow(investTransFlowBO);
        }


    }
}
